/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pkgjeudestrategie;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 *
 * @author Admin
 */
public class Monde extends JPanel implements Serializable {

    private Terrain tClicked;
    private ArrayList<Player> playerList;
    private ArrayList<Faction> factionList;
    private ArrayList<Terrain> terrainList;
    //n, c'est un indicatif de la grosseur du zoom
    private int n = 0;
    boolean gameIsOn=true;
    int nbPlayer;


public Monde(int nbPlayer){
    this.nbPlayer = nbPlayer;
    creation();
        setSize(10000, 10000);
        setLayout(null);
}
    public Monde(int nbPlayer,ArrayList<Player> playerList,
        ArrayList<Faction> factionList, ArrayList<Terrain> terrainList) {
        this.nbPlayer = nbPlayer;
        this.playerList = playerList;
        this.factionList = factionList;
        this.terrainList = terrainList;
       fillMonde();

        setSize(10000, 10000);
        setLayout(null);

    }

public void fillMonde(){
    int i=0;
   for(int x=0;x<10;x++){
       for(int y=0;y<10;y++){
                terrainList.get(i).setLocation(x * 400, y * 400);
                add(terrainList.get(i));
                i++;
       }
   }
        setCleanClic(0, 0);
}
    public void creation() {
        terrainList=new ArrayList();
        boolean zoneLibreB = true;
        boolean zoneInfranchissableB = true;
        for (int y = 0; y < 10; y++) {
            for (int i = 0; i < 10; i++) {

                Terrain terrain;
                zoneInfranchissableB = apparitionZoneInfranchissable();
                if (zoneInfranchissableB) {
                    terrain = new ZoneInfranchissable();
                } else if (!zoneInfranchissableB) {
                    zoneLibreB = apparitionZoneLibre();
                }
                if (zoneLibreB && !zoneInfranchissableB) {
                    terrain = new Territoire(false, nbPlayer);
                } else if (!zoneLibreB && !zoneInfranchissableB) {
                    terrain = new Territoire(true, nbPlayer);
                } else {
                    terrain = new ZoneInfranchissable();
                }

                terrain.setLocation(i * 400, y * 400);
                add(terrain);


                terrainList.add(terrain);

               

            }
        }

        setFactions();
        setCleanClic(0, 0);
    }

    public void setHapiness(int p) {
        for (Terrain t : terrainList) {
            if (t instanceof Territoire) {
                Territoire te = (Territoire) t;
                te.setHapiness(playerList.get(p).getFaction());
            }
        }
    }
    public void bombardement(int type,int player,Terrain t){
        Faction f1=playerList.get(player).getFaction();
        if(type==0){
            f1.didSomethingEthicallyWrong(-5);
            playerList.get(player).achat(750);
            t.removePopulation(0);
        }
        else if(type==1){
            f1.didSomethingEthicallyWrong(-20);
            playerList.get(player).achat(3000);
            t.removePopulation(1);
        }
        else if(type==2){
            f1.didSomethingEthicallyWrong(-25);
            playerList.get(player).achat(5000);
            t.removePopulation(2);
            JOptionPane.showMessageDialog(null,"Did something soooooo wrong");
        }
        t.actualizePopulation(f1,false);
    }
    public void hapinessCheck(int p){
        ArrayList<Territoire> lst=new ArrayList();
        Faction f=playerList.get(p).getFaction();
        for(Territoire t:f.getTerritoireList()){
        if(t.getHapiness(f)<20){
            Random rnd=new Random();
        int choice=rnd.nextInt(3);
        if(choice==0){
            JOptionPane.showMessageDialog(null,"Les citoyens ont pris le contrôle de "+t.getName()+" par la force. Vous ne possédez plus cette ville.");
            lst.add(t);
            factionList.add(new Faction(t,nbPlayer));
        }
        else if(choice==1){
            t.civilianCrisis();
        }
        
        
        }}
        f.getTerritoireList().removeAll(lst);
            seeDeadFactions();
    }
    public boolean relocate(int player){
        if(playerList.get(player).getFaction().getDrapeauRelocalisation()){
            return true;
        }
        return false;
    }
public void seeDeadFactions(){
    int nbActivePlayers=0;
    int playerPosition=0;
    int x=0;
    for(Faction f: factionList){
        if(f.getTerritoireList().size()<1){
            f.setDead();
        }
        
    }
    for(Player p:playerList){
        if(p.getFaction().isDead()){
            p.setDead();
        }
        else{nbActivePlayers++;playerPosition=x;}
        x++;
    }
    if(nbActivePlayers==1){
        gameOver(playerPosition);
    }
    
}
    public void setCleanClic(int player, int i) {
        for (Terrain t : terrainList) {
            t.setClicked(false);
        }
        if (i == 0) {
            tClicked = getTerritoireCapital(player);
           if(!playerList.get(player).isDead()){ getTerritoireCapital(player).setClicked(true);}
        }

    }

    public void colonise(Territoire t, int player) {
        ArrayList<Territoire> list = playerList.get(player).getFaction().getTerritoireList();
        for (Territoire te : list) {
            if (isPlayerTerritoireAround(te, t)) {
                setCleanClic(player, -1);
                tClicked = t;
                t.setClicked(true);
                t.setOccupied();
                t.setPlayer(player);
                playerList.get(player).getFaction().addTerritoire(t);

                return;
            }
        }
        JOptionPane.showMessageDialog(null, "Territoire trop éloigné pour être colonisé...");
    }

    public int getN() {
        return n;
    }

    public void actualizeRecherche() {
        for (Faction f : factionList) {
            f.getRecherche().upgradeRecherche();
        }
    }

    public void doUpgrades() {
        for (Terrain t : terrainList) {
            if (t instanceof Territoire) {
                Territoire te = (Territoire) t;
                if (te.isOccupied) {
                    t.timeUpgrade();
                }
            }
        }
    }

    public int getPosition(Territoire te) {
        int i = -1;
        for (int x = 0; x < terrainList.size(); x++) {
            if (terrainList.get(x) instanceof Territoire) {
                Territoire t = (Territoire) terrainList.get(x);
                if (t == te) {
                    i = x;
                }
            }
        }


        return i;
    }

    public boolean isPlayerTerritoireAround(Territoire you, Territoire wannaBe) {
        //doit être modifié si changements dans terrainList.
        int position = getPosition(you);
        try {
            if (terrainList.get(position - 1) == wannaBe) {
                return true;
            }
        } catch (Exception e) {
        }
        try {
            if (terrainList.get(position - 10) == wannaBe) {
                return true;
            }
        } catch (Exception e) {
        }
        try {
            if (terrainList.get(position - 9) == wannaBe) {
                return true;
            }
        } catch (Exception e) {
        }
        try {
            if (terrainList.get(position - 11) == wannaBe) {
                return true;
            }
        } catch (Exception e) {
        }
        try {
            if (terrainList.get(position + 1) == wannaBe) {
                return true;
            }
        } catch (Exception e) {
        }
        try {
            if (terrainList.get(position + 10) == wannaBe) {
                return true;
            }
        } catch (Exception e) {
        }
        try {
            if (terrainList.get(position + 9) == wannaBe) {
                return true;
            }
        } catch (Exception e) {
        }
        try {
            if (terrainList.get(position + 11) == wannaBe) {
                return true;
            }
        } catch (Exception e) {
        }
        return false;
    }

    public void setFactions() {
        for (int x = 0; x < nbPlayer; x++) {
            boolean eternity = true;
            int i = -1;
            while (eternity) {
                Random rnd = new Random();
                i = rnd.nextInt(terrainList.size());
                if (!terrainList.get(i).isZoneInfranchissable() && terrainList.get(i).isOccupied() && !terrainList.get(i).getCapital()) {
                    Territoire t = (Territoire) terrainList.get(i);
                    t.setPossessed(true);
                    t.setCapital(true);
                    eternity = false;
                }
            }
        }
        int y = 0;
        for (Terrain t : terrainList) {
            if (t instanceof Territoire) {
                Territoire te = (Territoire) t;
                if (te.isOccupied) {
                    Faction f = new Faction(te, nbPlayer);
                    try {
                    factionList.add(f);
                    } catch(NullPointerException e) {
                        factionList = new ArrayList<Faction>();
                        factionList.add(f);
                    }
                    if (te.getCapital()) {
                        Player p = new Player(f);
        try{
                        playerList.add(p);
                        }
        catch(NullPointerException e){
            playerList = new ArrayList<Player>();
            playerList.add(p);
        }
                        te.setPlayer(y);
                        y++;
                    }
                }
            }
        }

    }

    public Terrain getTerritoireCapital(int nbPlayer) {
        for (Terrain t : terrainList) {
            if (playerList.get(nbPlayer).getFaction().contains(t) && t.getCapital()) {

                return t;
            }
        }
        return null;
    }

    public boolean apparitionZoneLibre() {
        Random rnd = new Random();
        boolean b = false;
        b = isZoneInfranchissableAround();
        if (!b) {
            int i = rnd.nextInt(10);
            if (i != 0 && i != 1) {
                b = true;
            }
        }
        return b;
    }

    public boolean apparitionZoneInfranchissable() {
        Random rnd = new Random();
        boolean b;
        b = isZoneInfranchissableAround();
        if (!b) {
            int i = rnd.nextInt(10);
            if (i == 0) {
                b = true;
            }
        } else {
            int i = rnd.nextInt(5);
            if (i == 0) {
                b = true;
            } else {
                b = false;
            }
        }
        return b;
    }

    public ArrayList<Faction> getFactionList() {
        return factionList;
    }

    public ArrayList<Player> getPlayerList() {
        return playerList;
    }

    public ArrayList<Terrain> getTerrainList() {
        return terrainList;

    }

    public Terrain getClickedTerrainState() {
        for (Terrain t : terrainList) {
            if (t.isClicked()) {
                if (tClicked != t) {
                    tClicked.setClicked(false);
                    tClicked = t;
                }

            }
        }
        return tClicked;
    }

    public int[] getCapitale(int nbPlayer) {
        int[] tab = {0, 0};
        for (Terrain t : terrainList) {
            if (t instanceof Territoire) {
                Territoire newT = (Territoire) t;
                if (playerList.get(nbPlayer).getFaction().contains(newT) && newT.getCapital()) {
                    tab[0] = newT.getX() + getNewSize() / 2;
                    tab[1] = newT.getY() + getNewSize() / 2;
                    //tClicked = newT;
                    //newT.setClicked(true);
                }
            }
        }
        return tab;
    }

    public boolean isZoneInfranchissableAround() {
        //doit être modifié si changements dans terrainList.
        //n'observe que les terrains créés précédemment, pcq cette méthode est appelée directemment lors de la création de la carte
        try {
            if (terrainList.get(terrainList.size() - 1).isZoneInfranchissable()) {
                return true;
            }
        } catch (Exception e) {
        }
        try {
            if (terrainList.get(terrainList.size() - 10).isZoneInfranchissable()) {
                return true;
            }
        } catch (Exception e) {
        }
        try {
            if (terrainList.get(terrainList.size() - 9).isZoneInfranchissable()) {
                return true;
            }
        } catch (Exception e) {
        }
        try {
            if (terrainList.get(terrainList.size() - 11).isZoneInfranchissable()) {
                return true;
            }
        } catch (Exception e) {
        }
        return false;
    }

    public void setEcranStat(int player, EcranStats ecranStats) {

        playerList.get(player).actualiserEcranStat(ecranStats);
    }

    public void zoom(int zoom) {
        int size;
        boolean zoomB = false;
        if (zoom < 0 && n < 5) {
            n = n + 1;
            zoomB = true;
        } else if (zoom > 0 && n > -5) {
            n = n - 1;
            zoomB = true;
        } else {
            return;
        }
        size = getNewSize();
        if (zoomB) {
            int x = 0;
            int y = 0;
            for (Terrain t : terrainList) {
                t.zoom(size);
                //Image imgT = t.getImage().getScaledInstance(size, size, 1);
                //t.setImage(imgT);
                t.setLocation((int) (t.getWidth() * x), (int) (t.getHeight() * y));
                //pour faire tout le tableau !!
                if (x == 9) {
                    y++;
                    x = 0;
                } else {
                    x++;
                }
                //                           ii
            }
        }
        repaint();
    }

    public int getNewSize() {
        int size = 0;
        switch (n) {                 //nbr de terrains visibles!!
            case -5:
                size = 150;
                break;//   2
            case -4:
                size = 200;
                break;
            case -3:
                size = 250;
                break;
            case -2:
                size = 300;
                break;
            case -1:
                size = 350;
                break;
            case 0:
                size = 400;
                break;//   6
            case 1:
                size = 450;
                break;//   8
            case 2:
                size = 500;
                break;
            case 3:
                size = 550;
                break;
            case 4:
                size = 600;
                break;//  18
            case 5:
                size = 650;
                break;//  28
        }
        return size;
    }

    public void actualiserArgent() {
        for (Player p : playerList) {
            p.actualiserArgent();
        }
    }

    public void actualizePopulation(int i) {
        playerList.get(i).getFaction().actualizePopulation();
    }

    public void paintComponent(Graphics g) {
        g.setColor(Color.blue);
        g.fillRect(0, 0, 10000, 10000);
    }

    public int meilleurTrajectoireDeDéplacement(Territoire territoireDebut, Territoire territoireFin) {
        int quantiteDeTour = 0;
        int QuantiteDeTour2 = 0;
        int positionTerritoire = this.getPosition(territoireDebut);
        Terrain territoireAcote = territoireDebut;
        if (territoireDebut.getX() <= territoireFin.getX() && territoireDebut.getY() <= territoireFin.getY()) {
            quantiteDeTour = quantiteDeTour + territoireAcote.getquantiteDeTour();
            while ((territoireAcote.getX() < territoireFin.getX())) {

                positionTerritoire = positionTerritoire + 1;
                territoireAcote = this.terrainList.get(positionTerritoire);
                quantiteDeTour = quantiteDeTour + territoireAcote.getquantiteDeTour();
            }
            while ((territoireAcote.getY() < territoireFin.getY())) {

                positionTerritoire = positionTerritoire + 10;
                territoireAcote = this.terrainList.get(positionTerritoire);
                quantiteDeTour = quantiteDeTour + territoireAcote.getquantiteDeTour();

            }


        } else if (territoireDebut.getX() >= territoireFin.getX() && territoireDebut.getY() >= territoireFin.getY()) {
            quantiteDeTour = quantiteDeTour + territoireAcote.getquantiteDeTour();
            while ((territoireAcote.getX() > territoireFin.getX())) {
                positionTerritoire = positionTerritoire - 1;
                territoireAcote = this.terrainList.get(positionTerritoire);
                quantiteDeTour = quantiteDeTour + territoireAcote.getquantiteDeTour();

            }
            while ((territoireAcote.getY() < territoireFin.getY())) {

                positionTerritoire = positionTerritoire - 10;
                territoireAcote = this.terrainList.get(positionTerritoire);
                quantiteDeTour = quantiteDeTour + territoireAcote.getquantiteDeTour();
            }
        }
        System.out.println(quantiteDeTour);
        return quantiteDeTour;



    }

    public void actualiseRenfort() {
        Territoire temp2;
        for (Terrain temp : this.terrainList) {
            if (temp instanceof Territoire) {
                temp2 = (Territoire) temp;
                temp2.updateTourRenfort();
                temp = temp2;
            }
        }

    }
    public boolean isGameOn(){
        return gameIsOn;
    }
            
    public void gameOver(int playerNb){
        JOptionPane.showMessageDialog(null, "La partie est terminée. Le joueur "+(playerNb+1)+" a gagné.");
        gameIsOn=false;
    }
}
